#!/usr/pkg/bin/bash /usr/local/bin/bash

#
#
# Final CF SVN Id: make_dir_mdrd.sh 170 2007-02-19 08:47:55Z seklecki
# Google SVN $Id$
# ====
#

#/*
# * Copyright (c) 2006-2007 Collaborative Fusion, Inc.  All rights reserved.
# * 
# * Developed by: Collaborative Fusion, Inc.
# * 							http://www.collaborativefusion.com
# * 
# * Permission is hereby granted, free of charge, to any person obtaining a copy
# * of this software and associated documentation files (the "Software"), to
# * deal with the Software without restriction, including without limitation the
# * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# * sell copies of the Software, and to permit persons to whom the Software is
# * furnished to do so, subject to the following conditions:
# *   1. Redistributions of source code must retain the above copyright notice,
# *      this list of conditions and the following disclaimers.
# *   2. Redistributions in binary form must reproduce the above copyright
# *      notice, this list of conditions and the following disclaimers in the
# *      documentation and/or other materials provided with the distribution.
# *   3. All advertising materials mentioning features or use of this software
# *      must display the following acknowledgement: This product includes 
# *      software developed by Collaborative Fusion, Inc.
# *   4. Neither the name of Collaborative Fusion, Inc. or any of its employees
# *      may be used to endorse or promote products derived from this Software
# *      without specific prior written permission.
#
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
# * COLLABORATIVE FUSION, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
# * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# */
#
#/*
# * This code was written under funding by Collaborative Fusion, Inc..
# */
#


# this is an important check to catch non-bash interpreter
# that could lead to imporper variable subsitution by 
# ksh(1) and sh(1) that burned be bug time with an 'rm(1) -rf /'
# when $RD_ROOT did not get set.  I accidentally ran sh(1) $0.
# Luckily I controll-C'd it in-time, but lost parts of /bin

if [ `ps | grep $$ | egrep -v grep | awk '{print $5}'` != "bash" ]; then
	echo "FUCK ME FREDDY THIS ISN'T BASH I'M OUTTIE";
	exit 1;
fi


_intStepCount=0


if [ ! -f "./cf.conf" -a -r "./cf.conf" ]; then
	echo "Cannot find cf.conf in ./ ...bailing out!";
	exit 1;
else
	source ./cf.conf

	if [ $? -ne 0 ]; then
		echo "Reading Config Failed!"
		exit 1;
	fi
fi

#echo "DEBUG: $LOCALIZED_CONFIGS $LOCALIZED_CONFIGS_2TIER"

trap cleanup 1 2 3 14 15

echo "Building RD/MD Root on $PLATFORM for $FQDN ..."; good2go $?

# Step X:  Purge any stale RD Conents
echo "Step ${_intStepCount}: Purging stale ${RD_ROOT} contents" 

if [ -d $RD_ROOT ]; then
	echo -n "About to purge ${RD_ROOT}/*, confirm: [y/n]:"; 
	read answer
	if [ "$answer" != "y" ]; then
		exit 1;
	fi
	rm -rf $RD_ROOT/*; good2go $?
else
	echo "Cannot find & purge $RD_ROOT";
	exit 1;
fi



# Step X:  Build the RD Root heiarchy from DSTDIR
echo "Step ${_intStepCount}: Bringing over contents of RD from valid DSTDIR:"
cd $DSTDIR && $PAX -rw -pe $RD_ROOT_CONTENTS $RD_ROOT; good2go $?
cd $HOME_DIR

echo -n "RD Disk usage before prune:  "
du -hs $RD_ROOT

# Step X: Prune shit out of RD
echo -n "Step ${_intStepCount}: Pruning requested RD objects: " 
echo $RD_PRUNE_LIST

for b in $RD_PRUNE_LIST;  do
	rm -rf "$RD_ROOT/$b";
done;
good2go $?

echo -n "RD Disk usage after prune:  "
du -hs $RD_ROOT

# Step X: Build /dev
echo "Step ${_intStepCount}: Building new /dev:"
cd $RD_ROOT/dev && sh ./MAKEDEV all ;  good2go $?
cd $HOME_DIR

# Step X: Add missing directory anchors
echo "Step ${_intStepCount}: Making directory anchors"
mkdir -p $RD_ROOT/usr $RD_ROOT/shadow $RD_ROOT/cf $RD_ROOT/var/db/pkg ${THIRD_PARTY_ANCHOR}; good2go $?


# Step X: Mount CF Partitions in place (use MFS for now)
echo "Step ${_intStepCount}: Mounting MFS Anchors"
case $PLATFORM in
	openbsd)
		MFS_AGS="-S 1024 -s 2048"
		;;
	netbsd)
		MFS_ARGS="-s 2m"
esac

mount_mfs ${MFS_ARGS} swap $RD_ROOT/cf; good2go $?
mount_mfs ${MFS_ARGS} swap $RD_ROOT/shadow; good2go $?
mount_mfs ${MFS_ARGS} swap $RD_ROOT/usr; good2go $?
mount

 
# Step X: Add symlinks to Shadow and Boot
echo "Step ${_intStepCount}: Symlink'ing the Kernel over..."
case $PLATFORM in
	openbsd)
		cd $RD_ROOT/cf && echo > bsd && cd $RD_ROOT && ln -s ../cf/bsd ./bsd ; good2go $?
		;;
	netbsd)
		cd $RD_ROOT/cf && echo > netbsd && cd $RD_ROOT && ln -s ../cf/netbsd ./netbsd ; good2go $?
		;;		
esac
# This can be cleaned up


 
# Step X: Add global config file symlinks
echo "Step ${_intStepCount}: Symlink'ing global config files to /shadow/etc/"

# Remove these two because init(8) requires  a valid /etc/pwd.db at boot
# before we can even mount /dev/wd0b to /shadow =/
#	spwd.db \
#	pwd.db \
# and remove these to troubleshoot init(8) stupidity with single user mode transition
#	master.passwd \
#	passwd \
# this is fixed.  the $DSTDIR/etc/{,s}pwd.db are in place at boot until etc/rc.d/passwd
# populates all locaized users.


# Note: when we use "shadow/" here, we're referring to the MFS temp mount

# this code needs to be consolidated to account for two-tier directories
for a in $LOCALIZED_CONFIG_DIRS; do
	mkdir -p ${RD_ROOT}/shadow/etc/${a}
done ; good2go $?

# This code needs to be consolidated to account for two-tier directories
# About this:
# - First we create a zero-byte file on $rd_ro/sh/etc which is on MFS
#   -- Later, on a booted system, /shadow from template.$HOST will be there
# - Then we cd into the real rd/root etc and remove the copy from $reldir
# - Then we create a _relative_ path symlink
#   --  This prevents us from having to polute the build system
#   --  by refercing absolute path "/"
# - Then who knows what, Barry?


for a in $LOCALIZED_CONFIGS; do
	echo > $RD_ROOT/shadow/etc/$a;
	cd $RD_ROOT/etc;
	rm -f $a;
	ln -s ../shadow/etc/$a ${a};
done ; good2go $?

for b in $LOCALIZED_CONFIGS_2TIER; do
	echo > $RD_ROOT/shadow/etc/$b;
	cd $RD_ROOT/etc;
	rm -f $b;
	ln -s ../../shadow/etc/$b $b;
done ; good2go $?

# Step X: Initial customized log files
echo "Step ${_intStepCount}: Creating additional log file anchors for syslogd(8)"

cd ${RD_ROOT}/var/log && umask 027

for logfile in ${LOCALIZED_LOGFILES}; do
	touch ${logfile};
done; good2go $?

umask 022

# Step X: /home symlink
echo "Step ${_intStepCount}: Making /home and /root symlinks ..."
cd ${RD_ROOT} && mkdir -p shadow/home/ shadow/root && ln -s ./shadow/home/ ./home && rm -rf ./root && ln -s ./shadow/root ./root; good2go $?

# This is an ugly as hell set of Platform specific changes ~BAS
# Step X: Modify /etc/rc
echo "Step ${_intStepCount}: Patching /etc/rc ..."

# this check is nessecary to because sed(1) will exit code 0 even if "r"
# commands fail to find patch files

if [ ! -r ${RC_PATCH} ]; then
	echo "Unable to find rc(8) patch: ${RC_PATH}";
	cleanup
	exit 1;
fi

case ${PLATFORM} in
	netbsd)
		${SED} -E "15r ${RC_PATCH}" ${DSTDIR}/etc/rc > ${RD_ROOT}/etc/rc ; good2go $?
	;;
	openbsd)
		${SED} "144r ${RC_PATCH}" ${DSTDIR}/etc/rc > ${RD_ROOT}/etc/rc ; good2go $?
	;;
esac
	 
# Step X: Setting MFS Size
echo "Setting MFS size from ${MFS_USR_SIZE_MB} to ${MFS_USR_SIZE} in rc(8) / fstab(5)..."
cp ${RD_ROOT}/etc/rc ${RD_ROOT}/etc/rc.tmp && sed "s/MFSSIZE/${MFS_USR_SIZE}/" ${RD_ROOT}/etc/rc.tmp > ${RD_ROOT}/etc/rc; good2go $?

	
# Step X: Update version / revision / build data
echo "Step ${_intStepCount}: Patching /etc/rc with version / build revision ..."
cd ${RD_ROOT}/etc
cp -f rc rc.tmp
sed  "s%([[:alpha:]]){3}[[:space:]]([[:digit:]][[:digit:]]/){2}([[:digit:]][[:digit:]]){1}[[:space:]]([[:digit:]][[:digit:]]:){2}([[:digit:]][[:digit:]]){1}[[:space:]]-([[:digit:]]){4}[[:space:]]([[:alnum:]]){3}%$(date +"%a %D %T %z %Z")%" rc.tmp > rc  && rm -f rc.tmp; good2go $?
cd ${HOME_DIR}

# Step X: Update release engineer
echo "Step ${_intStepCount}: Patching /etc/rc with release engineer $SUDO_USER..."
cd ${RD_ROOT}/etc
cp -f rc rc.tmp
sed "s%USERNAME%$SUDO_USER%" rc.tmp > rc && rm -f rc.tmp ; good2go $?
cd ${HOME_DIR}

echo "Starting ${PLATFORM} specific changes..."
case $PLATFORM in
	netbsd)
		echo "Step ${_intStepCount}: Making special gzip(1), progress(1), libbz2 from /usr/bin available to rc(8): "
		cp -p ${DSTDIR}/usr/bin/gzip ${DSTDIR}/usr/bin/progress $RD_ROOT/bin; good2go $?
		
		# Step X: Modify /etc/rc.d/root to prevent umount(8)
		echo "Step ${_intStepCount}: Patching /etc/rc.d/root ..."
		sed -E 's/(.*umount.*)/\#\1/' ${DSTDIR}/etc/rc.d/root > ${RD_ROOT}/etc/rc.d/root ; good2go $?
		
		## Step X: Modify /etc/rc.d/mountall
		#echo "Patching /etc/rc.d/mountall ..."
		#sed -E "8s/^$/"\#\ BEFORE\:\ SERVERS"/" ${DSTDIR}/etc/rc.d/mountall > ${RD_ROOT}/etc/rc.d/mountall
		#This is commented out by a fix in rc.conf(5) using $critical_filesystems_local
		
		# Step X: Patch $shadow_root/etc/rc.d/dhc(client|pd)
		echo "Step ${_intStepCount}: Patch /etc/rc.d/dhc{pd,client} scripts for stateful database recovery..."
		cd ${HOME_DIR}
		patch -p0 < dhclient.diff ; good2go $?
		patch -p0 < dhcpd.diff ; good2go $?
		rm ${RD_ROOT}/etc/rc.d/*.orig
	
		# make it look more like OpenBSD!
		mkdir -p $RD_ROOT/var/chroot/named/etc $RD_ROOT/var/chroot/named/master ${RD_ROOT}/var/chroot/named/cache
		# this assumes the build-systems have been tampered with
		cp -rp  ${DSTDIR}/etc/namedb/* ${RD_ROOT}/var/chroot/named/master ; good2go $?
		mv ${RD_ROOT}/var/chroot/named/master/127 ${RD_ROOT}/var/chroot/named/master/127.zone
		
		echo "Step ${_intStepCount}: Putting etc/rc.d/passwd RC hook into place"
		cp ${HOME_DIR}/passwd ${RD_ROOT}/etc/rc.d/ && chmod 655 ${RD_ROOT}/etc/rc.d/passwd ; good2go $?
		
		mv ${RD_ROOT}/var/chroot/named/master/localhost ${RD_ROOT}/var/chroot/named/master/localhost.zone

	;;
	openbsd)
		# Step X: Modify /etc/rc to prevent umount(8)
		echo "Step ${_intStepCount}: Patching /etc/rc to prevent umount(8) ..."
		cp ${RD_ROOT}/etc/rc  ${RD_ROOT}/etc/rc.tmp && sed -e '/^umount/i\
		#' ${RD_ROOT}/etc/rc.tmp > ${RD_ROOT}/etc/rc && rm ${RD_ROOT}/etc/rc.tmp ; good2go $?

		# Step X: make a symlink to /tmp for /var/db/kvm_bsd.db
		echo "Step ${_intStepCount}: Putting symlinks in place for kvm_bsd(8)"
		touch ${RD_ROOT}/tmp/kvm_bsd.db && cd ${RD_ROOT}/var/db && ln -s ../../tmp/kvm_bsd.db ./kvm_bsd.db ; good2go $?
		touch ${RD_ROOT}/tmp/kvm_bsd.db.tmp && cd ${RD_ROOT}/var/db && ln -s ../../tmp/kvm_bsd.db.tmp ./kvm_bsd.db.tmp ; good2go $?
		cd ${HOME_DIR}

		# Step X: put gzip(1) in place
		echo "Step ${_intStepCount}: Putting a specially statically linked gzip(1)/compress(1) in place..."
		cp /usr/src/usr.bin/compress/compress ${RD_ROOT}/bin/gzip ; good2go $?
		cd ${HOME_DIR}

		# Step X: kill raidctl in rc(8)
		echo "Step ${_intStepCount}: Removing references to raidctl(8) in rc(8)..."
		cp ${RD_ROOT}/etc/rc  ${RD_ROOT}/etc/rc.tmp && sed '/raidctl/ i\
		true #' ${RD_ROOT}/etc/rc.tmp > ${RD_ROOT}/etc/rc && rm ${RD_ROOT}/etc/rc.tmp ; good2go $?

		# Step X: patch rc.shutdown(8)
		echo "Step ${_intStepCount}: Patch rc.shutdown(8) to maintain stateful data"
		echo "cp /etc/{,master.}passwd /etc/{,s}pwd.db /shadow/etc" >> ${RD_ROOT}/etc/rc.shutdown; good2go $?
	
	
	;;
esac

# Step X: Symlink /var/tmp to /tmp
echo "Step ${_intStepCount}: Symlink'ing /var/tmp to /tmp"
rm -rf ${RD_ROOT}/var/tmp && cd ${RD_ROOT}/var && ln -s /tmp ./tmp ; good2go $?

# Step X: Symlink symlink /var/cron
echo "Step ${_intStepCount}: Symlink'ing /var/cron to /shadow/var/cron"
rm -rf ${RD_ROOT}/var/cron
cd $RD_ROOT/var & ln -s ../shadow/var/cron ./cron ; good2go $?

# Step X: System-specific application changes
# Put anything here to "localize" the system service that
# will run on the system.
#Idea: call/exec() cfrd.$HOSTNAME instead?
echo "Step ${_intStepCount}: Running system-specific local application changes..."
# foo

cd ${HOME_DIR}

# Step X: Clean up
echo "Step ${_intStepCount}: Cleaning up..."
# dont call cleanup() on graceful exit
cleanup
